//
//  UIScrollView+EmptyTips.swift
//  CodingTest
//
//  Created by LYPC on 2021/11/18.
//

import UIKit
import SnapKit

public enum ScrollViewErrorType {
    case empty
    case error
    case custom(UIImage?)
    
    var image: UIImage? {
        switch self {
        case .empty:
            return .icon(.placeholder_empty)
        case .error:
            return .icon(.placeholder_error)
        case .custom(let img):
            return img
        }
    }
}

private var emptyViewkey: Void?
private var errorViewkey: Void?

public extension UIScrollView {
    
    var isEmpty: Bool {
        guard let emp = emptyView else { return true }
        return !emp.isHidden
    }
    var isError: Bool {
        guard let err = errorView else { return true }
        return !err.isHidden
    }
    var isShowingData: Bool {
        return !isEmpty && !isError
    }
    
    fileprivate var emptyView: UIView? {
        return objc_getAssociatedObject(self, &emptyViewkey) as? UIView
    }
    fileprivate var errorView: UIView? {
        return objc_getAssociatedObject(self, &errorViewkey) as? UIView
    }
    func setEmpty(type: ScrollViewErrorType = .empty, tips: NSAttributedString, callback: (() -> Void)? = nil) {
        let view = CTEmptyView(frame: bounds, tips: tips, type: type, onClick: callback)
        addSubview(view)
        view.snp.makeConstraints { (m) in
            m.left.top.equalTo(0)
            m.width.height.equalToSuperview()
        }
        view.backgroundColor = backgroundColor
        bringSubviewToFront(view)
        view.isHidden = true
        objc_setAssociatedObject(self, &emptyViewkey, view, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }
    func setError(tips: NSAttributedString, callback: (() -> Void)? = nil) {
        let view = CTEmptyView.init(frame: bounds, tips: tips, type: .error, onClick: callback)
        addSubview(view)
        view.snp.makeConstraints { (m) in
            m.left.top.equalTo(0)
            m.width.height.equalToSuperview()
        }
        view.backgroundColor = backgroundColor
        bringSubviewToFront(view)
        view.isHidden = true
        objc_setAssociatedObject(self, &errorViewkey, view, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }
    
    func placeEmpty(topY: CGFloat = 0, offsetY: CGFloat) {
        guard let view = emptyView as? CTEmptyView else { return }
        view.snp.updateConstraints { (m) in
            m.top.equalToSuperview().offset(topY)
            m.height.equalToSuperview().offset(-topY)
        }
        view.btn.snp.updateConstraints { (m) in
            m.top.equalTo(offsetY - btnTopMargin)
        }
    }
    func placeError(topY: CGFloat = 0, offsetY: CGFloat) {
        guard let view = errorView as? CTEmptyView else { return }
        view.snp.updateConstraints { (m) in
            m.top.equalToSuperview().offset(topY)
            m.height.equalToSuperview().offset(-topY)
        }
        view.btn.snp.updateConstraints { (m) in
            m.top.equalTo(offsetY - btnTopMargin)
        }
    }
    
    func hideError() {
        guard let errorView = errorView else { return }
        errorView.isHidden = true
    }
    func hideEmpty() {
        guard let emptyView = emptyView else { return }
        emptyView.isHidden = true
    }
    func disabledEmpty() {
        guard let emptyView = emptyView else { return }
        emptyView.isUserInteractionEnabled = false
    }
    func showScrError() {
        guard let errorView = errorView else { return }
        errorView.superview?.bringSubviewToFront(errorView)
        errorView.isHidden = false
        isScrollEnabled = false
    }
}

public extension UITableView {
    /// get empty view
    var empView: UIView? { return emptyView }
    var errView: UIView? { return errorView }
    
    /// 使用此方法来reloadData, reload完成后会根据数据源是否为空来显示emptyView
    func reloadData(_ callback: ((Bool) -> Void)? = nil) {
        reloadData()
        guard let empty = emptyView else { return }
        errorView?.isHidden = true
        var isEmpty = true
        if numberOfSections == 0 { isEmpty = true }
        else {
            if numberOfSections > 1 ||
                numberOfRows(inSection: 0) > 0 {
                isEmpty = false
            }
        }
        isScrollEnabled = !isEmpty
        empty.isHidden = !isEmpty
        callback?(isEmpty)
    }
    
    func showTableError() {
        guard let errorView = errorView else { return }
        if numberOfSections > 1 { return }
        if numberOfSections == 0 ||
            numberOfRows(inSection: 0) == 0 {
            reloadData()
            errorView.superview?.bringSubviewToFront(errorView)
            errorView.isHidden = false
            isScrollEnabled = false
        }
    }
}

private let btnTopMargin: CGFloat = 30
final class CTEmptyView: UIView {
    
    fileprivate var tipsOnClick: (() -> Void)?
    
    fileprivate var btn: CTEmptyBtn!
    private let imgMarginTitle: CGFloat = 14
    
    @objc private func p_actionTipsBtn() {
        tipsOnClick?()
    }
    @objc private func p_panGesture(pan: UIPanGestureRecognizer) {
        if pan.state == .ended {
            tipsOnClick?()
        }
    }
    init(frame: CGRect, tips: NSAttributedString, type: ScrollViewErrorType, onClick: (() -> Void)? = nil) {
        self.tipsOnClick = onClick
        super.init(frame: frame)
        
        
        let image = type.image
        imgHei = image?.size.height ?? 0
        imgHei = imgHei.ceil
        titleHei = tips.size().height
        btnHei = imgHei + titleHei + imgMarginTitle + btnTopMargin * 2
        
        btn = CTEmptyBtn()
        btn.imageView?.contentMode = .scaleAspectFit
        btn.titleLabel?.numberOfLines = 2
        btn.setImage(image, for: .normal)
        btn.setImage(image, for: .highlighted)
        btn.isAlphaHalfWhenHlight = true
        btn.setAttributedTitle(tips, for: .normal)
        btn.addTarget(self, action: #selector(p_actionTipsBtn), for: .touchDown)
        self.addSubview(btn)
        btn.isUserInteractionEnabled = onClick != nil
        let pan = UIPanGestureRecognizer.init(target: self, action: #selector(p_panGesture(pan:)))
        btn.addGestureRecognizer(pan)
        
        btn.snp.makeConstraints { (m) in
            m.width.equalToSuperview().inset(40)
            m.centerX.equalToSuperview()
            m.height.equalTo(btnHei)
            m.top.equalTo(150.fitR)
        }
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private var imgHei: CGFloat = 0
    private var titleHei: CGFloat = 0
    private var btnHei: CGFloat = 0
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        btn.imageViewFrame = CGRect(x: 0, y: btnTopMargin, width: btn.width, height: imgHei)
        btn.titleLabelFrame = CGRect(x: 0, y: btnHei - titleHei - btnTopMargin, width: btn.width, height: titleHei)
    }
}


final class CTEmptyBtn: UIButton {
    
    ///  设定label的frame
    var titleLabelFrame = CGRect.zero {
        didSet {
            self.setNeedsLayout()
        }
    }
    ///  设定image的frame
    var imageViewFrame = CGRect.zero {
        didSet {
            self.setNeedsLayout()
        }
    }
    ///  点击时 整个btn的alpha变为0.4
    var isAlphaHalfWhenHlight = false
    
    override func layoutSubviews() {
        super.layoutSubviews()
        if !imageViewFrame.isEmpty {
            imageView?.frame = imageViewFrame
        }
        if !titleLabelFrame.isEmpty {
            titleLabel?.frame = titleLabelFrame
        }
    }
    
    override var isHighlighted: Bool {
        didSet {
            if isAlphaHalfWhenHlight {
                if isHighlighted {
                    self.alpha = 0.4
                } else {
                    self.alpha = 1
                }
            }
        }
    }
}

